#pragma once

#include "defines.h"
#include "platform/vk/vk_device_context.h"
#include "platform/vk/vk_swapchain.h"
#include "core/camera.h"
#include "scene/mesh.h"
#include "scene/grid.h"
#include "scene/sprite2d.h"

namespace vkrender
{
    class MeshRenderer;
    class SpriteRenderer;
    class GridRenderer;

    struct MVPMatrices
    {
        glm::mat4 model;
        glm::mat4 view;
        glm::mat4 proj;
    };

    class RenderSystem
    {
    private:
        std::shared_ptr<VulkanDeviceContext> context;
        VulkanSwapChain* swapchain;
        uint32_t num_frames;
        std::vector<VkCommandBuffer> commandBuffers;

        uint32_t imageIndex;
        std::shared_ptr<Camera3D> camera3d;
        std::shared_ptr<Camera2D> camera2d;
        std::shared_ptr<SpriteRenderer> sprite_renderer;
        std::shared_ptr<MeshRenderer> mesh_renderer;
        std::shared_ptr<GridRenderer> grid_renderer;

        std::shared_ptr<VulkanModel> mesh;
        std::shared_ptr<Grid> grid;
        
    public:
        RenderSystem(
            const std::shared_ptr<VulkanDeviceContext>& context,
            const std::shared_ptr<VulkanSwapChain>& swapchain);
        ~RenderSystem();

        bool beginFrame();
        bool endFrame();

        VkCommandBuffer beginScene();
        VkCommandBuffer endScene();

        void DrawScene(VkExtent2D extent);

        void adjustForSwapchain(const std::shared_ptr<VulkanSwapChain>& swapchain);
    private:
        void createCommandBuffers();
        void freeCommandBuffers();
    };
}
